/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_API_COLLECTIONS_MAP_HPP
#define	_CUBEFS_CORE_API_COLLECTIONS_MAP_HPP

#include <cubefs/api/models/map.hpp>
#include <cubefs/core/api/models/collection.hpp>

#define CUBEFS_SOURCE "cubefs/core/api/collections/map.hpp:" CUBEFS_AT

namespace cubefs    {
namespace api       {


template <typename Interface>
class PairImplT: public TypedImplT<Interface> {
	typedef PairImplT<Interface>	Me;
	typedef TypedImplT<Interface>	Base;

	Typed *key_, *value_;
	Int idx_;

public:
	PairImplT(Typed *key, Typed *value, Int idx = 0): key_(key), value_(value), idx_(idx) {};

	virtual ~PairImplT() throw () {
		delete key_;
		delete value_;
	}

	virtual Typed *key() const {
		return key_;
	}

	virtual Typed *value() const {
		return value_;
	}

	virtual Int GetIdx() const {
		return idx_;
	}

	virtual void SetIdx(Int idx) {
		idx_ = idx;
	}

	virtual bool managed() {
		return false;
	}

	virtual void CheckKeyNotNull() {
		if (key_ == NULL) {
			throw NullPointerException(CUBEFS_SOURCE, "Pair.key value mast not be null");
		}
	}

	virtual void CheckValueNotNull() {
		if (value_ == NULL) {
			throw NullPointerException(CUBEFS_SOURCE, "Pair.value value mast not be null");
		}
	}

	virtual void CheckKVNotNull() {
		CheckKeyNotNull();
		CheckValueNotNull();
	}

	static void Init() {
	    AbstractType *type = new AbstractType(TypeNameFactory<Interface>::name(), Typed::MyType());
	    type_ = type;

	    type->AddOperation(new BasicOperation<Typed* (Me::*)(), Typed* (Me::*)() const>(type, TypedImpl::MyType(), "key", &Me::key));
	    type->AddOperation(new BasicOperation<Typed* (Me::*)(), Typed* (Me::*)() const>(type, TypedImpl::MyType(), "value", &Me::value));

	    type->AddOperation(new BasicOperation<Int (Me::*)(), Int (Me::*)() const>(type, "GetIdx", &Me::GetIdx));
	    type->AddOperation(new BasicOperation<void (Me::*)(Int)>(type, "SetIdx", "idx", &Me::SetIdx));
	}

	CUBEFS_DECLARE_REFLECTION;
};

template <typename Interface>
Type* PairImplT<Interface>::type_		= NULL;
typedef PairImplT<Map::Pair>			PairImpl;

CUBEFS_DEFINE_PARAMETER_TYPE(Map::Pair);




template <typename Interface>
class MapImplT: public CollectionImplT<Interface> {
	typedef MapImplT<Interface>			Me;
	typedef CollectionImplT<Interface> 	Base;

public:

    virtual bool Get(Map::Pair* pair)            = 0;
    virtual void Put(Map::Pair* pair)            = 0;
    virtual bool Remove(Map::Pair *key)          = 0;

    virtual Map::Pair* CreatePairHolder()        = 0;
    
    static void Init() {
        AbstractType *type = new AbstractType(TypeNameFactory<Interface>::name(), Collection::MyType());
        type_ = type;

        type->AddOperation(new BasicOperation<bool (Me::*)(Map::Pair*)>(type, "Get", "pair", &Me::Get));
        type->AddOperation(new BasicOperation<void (Me::*)(Map::Pair*)>(type, "Put", "pair", &Me::Put));

        type->AddOperation(new BasicOperation<Typed* (Me::*)(), Map::Pair* (Me::*)()>(type, PairImpl::MyType(), "CreatePairHolder", &Me::CreatePairHolder));

        type->AddOperation(new BasicOperation<bool (Me::*)(Map::Pair*)>(type, "Remove", "key", &Me::Remove));
    }

    CUBEFS_DECLARE_REFLECTION;
};

template <typename Interface>
Type* MapImplT<Interface>::type_		= NULL;
typedef MapImplT<cubefs::api::Map>		MapImpl;



}
}

#undef CUBEFS_SOURCE

#endif
